﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace MultiWallpaperManager
{
	class WallpaperChanger
	{
		ScreenInformation[] screens;
		MyRectangle entireRect;

		public WallpaperChanger(ScreenInformation[] screens, MyRectangle entireRect)
		{
			this.screens = screens;
			this.entireRect = entireRect;
		}

		/// <summary>
		/// 바탕화면 변경
		/// </summary>
		/// <param name="keepCurrentImage">이미지를 바꾸지 않는다.</param>
		public void ChangeWallpaper(bool keepCurrentImage)
		{
			const string WallpaperFileName = "MultiWallpaper.bmp";

			string picturesPath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
												WallpaperFileName);

			try
			{
				SaveWallpaperBitmap(picturesPath, keepCurrentImage);

				WindowsAPI.SetDesktopBackground(picturesPath, DesktopBackgroundStyle.Tiled);
			}
			catch (Exception)
			{
				MessageBox.Show(Resource.CannotChangeWallpaper, Resource.MessageBoxTitle);
			}
		}

		public void SaveWallpaperBitmap(string savePath, bool keepCurrentImage)
		{
			/*
			 * 그리는 방법
			 * 1. 데스크탑이 상하인지 좌우인지 판별한다.
			 * 2. primary screen을 먼저 그린다.
			 * 3. 상하일경우엔 스크린 위치의 y값을 무시하고 아래로 그린다.
			 * 4. 좌우일경우 스크린 위치의 x값을 무시하고 오른쪽으로 그린다. 
			 */

			int widthSum = 0, heightSum = 0;
			Size bmpSize = new Size();

			foreach (ScreenInformation screen in screens)
			{
				widthSum += screen.bounds.Width;
				heightSum += screen.bounds.Height;
			}

			// determination
			bool horizontal = false;

			if (entireRect.Width < widthSum)
			{
				horizontal = false;
			}
			else if (entireRect.Height < heightSum)
			{
				horizontal = true;
			}
			else
			{
				// error
			}

			// calculate bmp size
			bmpSize.Width = entireRect.Width;
			bmpSize.Height = entireRect.Height;

			// make bitmap
			Bitmap bmp = new Bitmap(bmpSize.Width, bmpSize.Height);
			Graphics graphics = Graphics.FromImage(bmp);
			Point drawPosition = new Point();

			// primary 를 먼저 놓도록 인덱스를 만듬.
			int[] index = new int[screens.Length];

			for (int i = 0; i < index.Length; i++)
				index[i] = i;

			for (int i = 0; i < index.Length; i++)
			{
				ScreenInformation screen = screens[i];

				if (screen.primary)
				{
					Swap(ref index[0], ref index[i]);
				}
			}

			// draw
			for (int j = 0; j < index.Length; j++)
			{
				int i = index[j];

				ScreenInformation screen = screens[i];
				Image image = Image.FromFile(screen.GetProperImageFilePath(keepCurrentImage));

				if (horizontal)
					drawPosition.Y = screen.bounds.Top;
				else
					drawPosition.X = screen.bounds.Left;

				// draw here
			//	graphics.DrawImage(image, drawPosition);	// 크기가 정확하게 안그려짐.
				graphics.DrawImage(image, drawPosition.X, drawPosition.Y, screen.bounds.Width, screen.bounds.Height);

				// if position is negative, draw twice
				Point newPosition = new Point(drawPosition.X, drawPosition.Y);

				if (drawPosition.X < 0)
					newPosition.X += bmpSize.Width;

				if (drawPosition.Y < 0)
					newPosition.Y += bmpSize.Height;

				if (drawPosition.X < 0 || drawPosition.Y < 0)
					graphics.DrawImage(image, newPosition);

				if (horizontal)
					drawPosition.X += screen.bounds.Width;
				else
					drawPosition.Y += screen.bounds.Height;

				// clean up
				image.Dispose();
			}

			bmp.Save(savePath, ImageFormat.Bmp);

			// clean up
			bmp.Dispose();
			graphics.Dispose();
		}

		private void Swap(ref int a, ref int b)
		{
			int temp = a;
			a = b;
			b = temp;
		}

	}
}
